"""
字典导入导出功能
支持Excel、JSON、CSV格式的数据导入导出
"""

import logging
import json
import csv
import io
from typing import Dict, Any, List, Optional, Union
from datetime import datetime
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, Alignment, PatternFill

from src.app.modules.dictionary.service import DictionaryService
from src.app.modules.dictionary.utils import DictionaryUtils

logger = logging.getLogger(__name__)

class DictionaryImportExport:
    """字典导入导出类"""
    
    def __init__(self):
        self.service = DictionaryService()
        self.utils = DictionaryUtils()
    
    def export_to_excel(self, dict_type: str = None, file_path: str = None) -> Dict[str, Any]:
        """
        导出字典数据到Excel文件
        
        Args:
            dict_type: 字典类型（可选）
            file_path: 导出文件路径（可选）
            
        Returns:
            导出结果
        """
        try:
            # 获取数据
            if dict_type:
                dictionaries = self.service.get_dictionaries_by_type(dict_type)
                tree_data = {dict_type: self.utils.build_tree_structure(dictionaries)}
            else:
                types = self.service.get_all_types()
                tree_data = {}
                for type_name in types:
                    dictionaries = self.service.get_dictionaries_by_type(type_name)
                    tree_data[type_name] = self.utils.build_tree_structure(dictionaries)
            
            # 创建工作簿
            wb = Workbook()
            
            # 删除默认工作表
            wb.remove(wb.active)
            
            # 设置样式
            header_font = Font(name='Microsoft YaHei', size=12, bold=True, color='FFFFFF')
            header_fill = PatternFill(start_color='366092', end_color='366092', fill_type='solid')
            header_alignment = Alignment(horizontal='center', vertical='center')
            
            cell_font = Font(name='Microsoft YaHei', size=10)
            cell_alignment = Alignment(horizontal='left', vertical='center')
            
            # 创建工作表
            for dict_type, tree_nodes in tree_data.items():
                ws = wb.create_sheet(title=dict_type[:31])  # Excel工作表名称限制31字符
                
                # 写入表头
                headers = ['字典ID', '字典类型', '字典代码', '字典名称', '父级代码', 
                          '排序号', '系统字典', '描述', '创建时间', '更新时间']
                for col, header in enumerate(headers, 1):
                    cell = ws.cell(row=1, column=col, value=header)
                    cell.font = header_font
                    cell.fill = header_fill
                    cell.alignment = header_alignment
                
                # 写入数据
                row = 2
                flat_data = self.utils.flatten_tree(tree_nodes)
                for item in flat_data:
                    ws.cell(row=row, column=1, value=item['dict_id'])
                    ws.cell(row=row, column=2, value=item['dict_type'])
                    ws.cell(row=row, column=3, value=item['dict_code'])
                    ws.cell(row=row, column=4, value=item['dict_name'])
                    ws.cell(row=row, column=5, value=item['parent_code'] or '')
                    ws.cell(row=row, column=6, value=item['sort_order'])
                    ws.cell(row=row, column=7, value='是' if item['is_system'] else '否')
                    ws.cell(row=row, column=8, value=item['description'] or '')
                    ws.cell(row=row, column=9, value=item['create_time'] or '')
                    ws.cell(row=row, column=10, value=item['update_time'] or '')
                    
                    # 设置单元格样式
                    for col in range(1, 11):
                        cell = ws.cell(row=row, column=col)
                        cell.font = cell_font
                        cell.alignment = cell_alignment
                    
                    row += 1
                
                # 调整列宽
                column_widths = [20, 15, 15, 20, 15, 8, 10, 30, 20, 20]
                for col, width in enumerate(column_widths, 1):
                    ws.column_dimensions[chr(64 + col)].width = width
                
                # 冻结首行
                ws.freeze_panes = 'A2'
            
            # 保存文件
            if file_path:
                wb.save(file_path)
                logger.info(f"字典数据导出到Excel成功: {file_path}")
                return {
                    'success': True,
                    'file_path': file_path,
                    'message': f'导出成功，共{len(tree_data)}个类型'
                }
            else:
                # 返回字节流
                buffer = io.BytesIO()
                wb.save(buffer)
                buffer.seek(0)
                
                return {
                    'success': True,
                    'data': buffer.getvalue(),
                    'filename': f'dictionary_export_{datetime.now().strftime("%Y%m%d_%H%M%S")}.xlsx',
                    'message': f'导出成功，共{len(tree_data)}个类型'
                }
                
        except Exception as e:
            logger.error(f"导出Excel失败: {e}")
            return {
                'success': False,
                'message': f'导出Excel失败: {str(e)}'
            }
    
    def import_from_excel(self, file_path: str, overwrite: bool = False) -> Dict[str, Any]:
        """
        从Excel文件导入字典数据
        
        Args:
            file_path: Excel文件路径
            overwrite: 是否覆盖现有数据
            
        Returns:
            导入结果
        """
        try:
            # 加载工作簿
            wb = load_workbook(file_path)
            
            success_count = 0
            error_count = 0
            errors = []
            
            # 处理每个工作表
            for sheet_name in wb.sheetnames:
                ws = wb[sheet_name]
                
                # 读取表头
                headers = []
                for cell in ws[1]:
                    headers.append(cell.value)
                
                # 验证表头
                required_headers = ['字典类型', '字典代码', '字典名称']
                if not all(header in headers for header in required_headers):
                    errors.append(f"工作表'{sheet_name}'缺少必要的表头列")
                    continue
                
                # 读取数据行
                for row in range(2, ws.max_row + 1):
                    try:
                        row_data = {}
                        for col, header in enumerate(headers):
                            cell_value = ws.cell(row=row, column=col + 1).value
                            row_data[header] = cell_value
                        
                        # 转换数据
                        dict_data = {
                            'dict_type': row_data['字典类型'],
                            'dict_code': str(row_data['字典代码']).strip(),
                            'dict_name': str(row_data['字典名称']).strip(),
                            'parent_code': str(row_data.get('父级代码', '')).strip() or None,
                            'sort_order': int(row_data.get('排序号', 0)),
                            'is_system': row_data.get('系统字典') == '是',
                            'description': str(row_data.get('描述', '')).strip() or ''
                        }
                        
                        # 验证数据
                        validation = self.service.validate_dictionary_data(dict_data)
                        if not validation['valid']:
                            error_count += 1
                            errors.append(f"行{row}: {', '.join(validation['errors'])}")
                            continue
                        
                        # 导入数据
                        result = self.service.create_dictionary(dict_data)
                        if result['success']:
                            success_count += 1
                        else:
                            error_count += 1
                            errors.append(f"行{row}: {result['message']}")
                            
                    except Exception as e:
                        error_count += 1
                        errors.append(f"行{row}: 处理失败 - {str(e)}")
            
            return {
                'success': error_count == 0,
                'message': f'导入完成：成功{success_count}条，失败{error_count}条',
                'success_count': success_count,
                'error_count': error_count,
                'errors': errors
            }
            
        except Exception as e:
            logger.error(f"导入Excel失败: {e}")
            return {
                'success': False,
                'message': f'导入Excel失败: {str(e)}'
            }
    
    def export_to_json(self, dict_type: str = None, file_path: str = None) -> Dict[str, Any]:
        """
        导出字典数据到JSON文件
        
        Args:
            dict_type: 字典类型（可选）
            file_path: 导出文件路径（可选）
            
        Returns:
            导出结果
        """
        try:
            # 获取数据
            export_data = self.utils.export_to_dict(dict_type)
            
            # 转换为JSON字符串
            json_str = json.dumps(export_data, ensure_ascii=False, indent=2)
            
            if file_path:
                with open(file_path, 'w', encoding='utf-8') as f:
                    f.write(json_str)
                logger.info(f"字典数据导出到JSON成功: {file_path}")
                return {
                    'success': True,
                    'file_path': file_path,
                    'message': f'导出成功，共{len(export_data.get("data", {}))}个类型'
                }
            else:
                return {
                    'success': True,
                    'data': json_str,
                    'filename': f'dictionary_export_{datetime.now().strftime("%Y%m%d_%H%M%S")}.json',
                    'message': f'导出成功，共{len(export_data.get("data", {}))}个类型'
                }
                
        except Exception as e:
            logger.error(f"导出JSON失败: {e}")
            return {
                'success': False,
                'message': f'导出JSON失败: {str(e)}'
            }
    
    def import_from_json(self, file_path: str, overwrite: bool = False) -> Dict[str, Any]:
        """
        从JSON文件导入字典数据
        
        Args:
            file_path: JSON文件路径
            overwrite: 是否覆盖现有数据
            
        Returns:
            导入结果
        """
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                import_data = json.load(f)
            
            return self.utils.import_from_dict(import_data, overwrite)
            
        except Exception as e:
            logger.error(f"导入JSON失败: {e}")
            return {
                'success': False,
                'message': f'导入JSON失败: {str(e)}'
            }
    
    def export_to_csv(self, dict_type: str, file_path: str = None) -> Dict[str, Any]:
        """
        导出字典数据到CSV文件
        
        Args:
            dict_type: 字典类型
            file_path: 导出文件路径（可选）
            
        Returns:
            导出结果
        """
        try:
            # 获取数据
            dictionaries = self.service.get_dictionaries_by_type(dict_type)
            if not dictionaries:
                return {
                    'success': False,
                    'message': f'字典类型"{dict_type}"不存在或无数据'
                }
            
            # 创建CSV内容
            output = io.StringIO()
            writer = csv.writer(output)
            
            # 写入表头
            headers = ['字典ID', '字典类型', '字典代码', '字典名称', '父级代码', 
                      '排序号', '系统字典', '描述', '创建时间', '更新时间']
            writer.writerow(headers)
            
            # 写入数据
            for item in dictionaries:
                row = [
                    item['dict_id'],
                    item['dict_type'],
                    item['dict_code'],
                    item['dict_name'],
                    item['parent_code'] or '',
                    item['sort_order'],
                    '是' if item['is_system'] else '否',
                    item['description'] or '',
                    item['create_time'] or '',
                    item['update_time'] or ''
                ]
                writer.writerow(row)
            
            csv_str = output.getvalue()
            output.close()
            
            if file_path:
                with open(file_path, 'w', encoding='utf-8-sig', newline='') as f:
                    f.write(csv_str)
                logger.info(f"字典数据导出到CSV成功: {file_path}")
                return {
                    'success': True,
                    'file_path': file_path,
                    'message': f'导出成功，共{len(dictionaries)}条记录'
                }
            else:
                return {
                    'success': True,
                    'data': csv_str,
                    'filename': f'{dict_type}_{datetime.now().strftime("%Y%m%d_%H%M%S")}.csv',
                    'message': f'导出成功，共{len(dictionaries)}条记录'
                }
                
        except Exception as e:
            logger.error(f"导出CSV失败: {e}")
            return {
                'success': False,
                'message': f'导出CSV失败: {str(e)}'
            }
    
    def get_export_template(self, format_type: str = 'excel') -> Dict[str, Any]:
        """
        获取导入模板
        
        Args:
            format_type: 模板格式（excel/csv）
            
        Returns:
            模板数据
        """
        try:
            template_data = [
                {
                    'dict_id': '',
                    'dict_type': '示例类型',
                    'dict_code': 'EXAMPLE_001',
                    'dict_name': '示例字典',
                    'parent_code': '',
                    'sort_order': 1,
                    'is_system': False,
                    'description': '这是一个示例字典项',
                    'create_time': '',
                    'update_time': ''
                },
                {
                    'dict_id': '',
                    'dict_type': '示例类型',
                    'dict_code': 'EXAMPLE_002',
                    'dict_name': '子级字典',
                    'parent_code': 'EXAMPLE_001',
                    'sort_order': 2,
                    'is_system': False,
                    'description': '这是一个子级字典项',
                    'create_time': '',
                    'update_time': ''
                }
            ]
            
            if format_type == 'excel':
                wb = Workbook()
                ws = wb.active
                ws.title = '字典导入模板'
                
                # 写入表头
                headers = ['字典类型*', '字典代码*', '字典名称*', '父级代码', '排序号', '系统字典', '描述']
                for col, header in enumerate(headers, 1):
                    ws.cell(row=1, column=col, value=header)
                
                # 写入示例数据
                for row, item in enumerate(template_data, 2):
                    ws.cell(row=row, column=1, value=item['dict_type'])
                    ws.cell(row=row, column=2, value=item['dict_code'])
                    ws.cell(row=row, column=3, value=item['dict_name'])
                    ws.cell(row=row, column=4, value=item['parent_code'])
                    ws.cell(row=row, column=5, value=item['sort_order'])
                    ws.cell(row=row, column=6, value='否')
                    ws.cell(row=row, column=7, value=item['description'])
                
                # 调整列宽
                for col in range(1, 8):
                    ws.column_dimensions[chr(64 + col)].width = 15
                
                # 返回字节流
                buffer = io.BytesIO()
                wb.save(buffer)
                buffer.seek(0)
                
                return {
                    'success': True,
                    'data': buffer.getvalue(),
                    'filename': 'dictionary_import_template.xlsx',
                    'message': '模板生成成功'
                }
                
            elif format_type == 'csv':
                output = io.StringIO()
                writer = csv.writer(output)
                
                # 写入表头
                headers = ['字典类型*', '字典代码*', '字典名称*', '父级代码', '排序号', '系统字典', '描述']
                writer.writerow(headers)
                
                # 写入示例数据
                for item in template_data:
                    row = [
                        item['dict_type'],
                        item['dict_code'],
                        item['dict_name'],
                        item['parent_code'],
                        item['sort_order'],
                        '否',
                        item['description']
                    ]
                    writer.writerow(row)
                
                csv_str = output.getvalue()
                output.close()
                
                return {
                    'success': True,
                    'data': csv_str,
                    'filename': 'dictionary_import_template.csv',
                    'message': '模板生成成功'
                }
                
        except Exception as e:
            logger.error(f"生成模板失败: {e}")
            return {
                'success': False,
                'message': f'生成模板失败: {str(e)}'
            }